﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using ProtetoresDaMata.Objects;
using ProtetoresDaMata.Physics;
using ProtetoresDaMata.Smarts;

namespace ProtetoresDaMata
{
    public partial class GamePage : PhoneApplicationPage
    {
        //Base Game
        ContentManager contentManager;
        GameTimer timer;
        SpriteBatch spriteBatch;
        UIElementRenderer uiRenderer;
        GameTimerEventArgs timeEventsArgs;
        Enumerators.GameState GameState;

        //Smarts
        PhysicsBase physics;
        Camera camera;
        Helpers helpers;

        //Objects in Scenario
        //public Floor floor;
        public Character character;
        public List<ScenarioObject> floors;
        public List<ScenarioObject> obstacles;
        public List<ScenarioObject> bonus;
        public List<ScenarioObject> montains;
        public ScenarioObject sun;
        public ScenarioObject moon;

        int bonusValueBase;

        //Game Properties
        protected double playerScore;
        protected DateTime dateGame;
        protected DateTime lastTapButtonTime;
        protected bool collisionObstacles = false;
        protected bool collisionHoles = false;
        public bool dayNight = false;

        public GamePage()
        {
            InitializeComponent();

            // Get the content manager from the application
            contentManager = (Application.Current as App).Content;

            //Create a timer for this page
            timer = new GameTimer();
            timer.UpdateInterval = TimeSpan.FromTicks(1 / 60);
            timer.Update += OnUpdate;
            timer.Draw += OnDraw;

            //Initialize Smarts
            physics = new PhysicsBase();

            //Initialize Properties
            dateGame = DateTime.Today;
            playerScore = 0;

            //Change game state
            GameState = Enumerators.GameState.Play;

            // We use the LayoutUpdated event in order to handle creation of the UIElementRenderer
            LayoutUpdated += new EventHandler(GamePage_LayoutUpdated);

        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // Set the sharing mode of the graphics device to turn on XNA rendering
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);

            // TODO: use this.content to load your game content here

            //Initialize Camera (Shared Viewport)
            camera = new Camera(SharedGraphicsDeviceManager.Current.GraphicsDevice.Viewport);

            //Initialize objects
            //floor = new Floor();
            character = new Character();
            floors = new List<ScenarioObject>();
            obstacles = new List<ScenarioObject>();
            bonus = new List<ScenarioObject>();
            montains = new List<ScenarioObject>();
            helpers = new Helpers();

            //Load Objects Properties
            //floor.LoadPropertiesDefault(contentManager);
            character.LoadPropertiesDefault(contentManager);
            helpers.LoadSounds(contentManager);

            helpers.LoadPropertiesScenarioObjects(contentManager);
            helpers.BuildInitialFloor(ref floors);
            helpers.BuildInitialMontains(ref montains);
            helpers.LoadSunMoon(ref sun, ref moon);

            //Set Positions
            //floor.CenterAt();
            character.CenterAtLocation(new Vector2(100, 320));

            // Start the timer
            timer.Start();

            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // Stop the timer
            timer.Stop();

            // Set the sharing mode of the graphics device to turn off XNA rendering
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(false);

            base.OnNavigatedFrom(e);
        }

        /// <summary>
        /// Allows the page to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        private void OnUpdate(object sender, GameTimerEventArgs timeEvents)
        {
            // TODO: Add your update logic here
            TouchCollection touches = TouchPanel.GetState();

            timeEventsArgs = timeEvents;

            physics.InitiJump(character, timeEvents);

            //Moviments
            helpers.CharacterMoviment(ref character);
            helpers.DayNightTransition(camera.Position.X, ref dayNight);
            helpers.DayNightChange(ref sun, ref moon, dayNight);

            //Collisions Verify
            collisionHoles = helpers.ObstaclesCollisionsVerify(floors, character);
            collisionObstacles = helpers.ObstaclesCollisionsVerify(obstacles, character);
            bonusValueBase = helpers.BonusCollisionsVerify(ref bonus, character);


            helpers.BuildContinuityFloor(ref floors, camera.Position.X);
            helpers.BuildObstacles(floors, ref obstacles, camera.Position.X);
            helpers.BuildBonusIcons(floors, obstacles, ref bonus, camera.Position.X);
            helpers.BuildContinuosMontains(ref montains, camera.Position.X);
            //Camera update
            camera.Update(timeEvents, this);

            //Score update
            helpers.DistanceScoreUpdate(character, this.tb_distanceScore);
            helpers.IconsScoreUpdate(bonusValueBase, tb_iconsScore);
        }

        /// <summary>
        /// Allows the page to draw itself.
        /// </summary>
        private void OnDraw(object sender, GameTimerEventArgs e)
        {
            switch (GameState)
            {
                case Enumerators.GameState.Play:
                    // Draw the Silverlight UI into the texture
                    uiRenderer.Render();

                    helpers.CollisionObstacles(collisionHoles, collisionObstacles, ref GameState);

                    SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.Azure);

                    // TODO: Add your drawing code here
                    spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, camera.transform);
                    //spriteBatch.Begin();

                    //floor.Draw(spriteBatch);

                    sun.Draw(spriteBatch);
                    moon.Draw(spriteBatch);

                    helpers.DrawObjects(spriteBatch, new[] { montains, floors, obstacles, bonus, });
                    character.Draw(spriteBatch);


                    // Draw the UI on top of the scene
                    spriteBatch.Draw(uiRenderer.Texture, new Vector2(camera.Position.X, 0), Color.White);

                    spriteBatch.End();
                    break;
                case Enumerators.GameState.Stoped:
                    break;
                case Enumerators.GameState.Over:

                    NavigationService.Navigate(new Uri("/RankingPostPage.xaml?IconsScore=" + tb_iconsScore.Text +
                                                                             "&DistanceScore=" + tb_distanceScore.Text, UriKind.Relative));


                    break;
                default:
                    break;
            }


        }

        /// <summary>
        /// Game page layout update
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void GamePage_LayoutUpdated(object sender, EventArgs e)
        {

            int width = (int)ActualWidth;
            int height = (int)ActualHeight;

            // Ensure the page size is valid
            if (width <= 0 || height <= 0)
                return;

            // Do we already have a UIElementRenderer of the correct size?
            if (uiRenderer != null &&
                uiRenderer.Texture != null &&
                uiRenderer.Texture.Width == width &&
                uiRenderer.Texture.Height == height)
            {
                return;
            }

            // Before constructing a new UIElementRenderer, be sure to Dispose the old one
            if (uiRenderer != null)
                uiRenderer.Dispose();

            // Create the renderer
            uiRenderer = new UIElementRenderer(this, width, height);

        }

        #region Events Methods

        /// <summary>
        /// Jump button event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void JumpButton_Click(object sender, RoutedEventArgs e)
        {
            physics.jump = true;
            physics.action = false;
        }

        /// <summary>
        /// Double jump event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoubleJumpButton_Click(object sender, RoutedEventArgs e)
        {
            physics.doubleJump = true;
            physics.action = false;
        }

        /// <summary>
        /// Slide button event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SlideButton_Click(object sender, RoutedEventArgs e)
        {
            physics.doubleJump = true;
            physics.action = false;
        }

        #endregion
    }
}